/*
 * Copyright (c) 2020 - ~, HIT_HERO Team
 *
 * BLUETOOTH HC06 MODULE SOUCE FILE
 * Used in RT-Thread Operate System
 *
 * Change Logs:
 * Date           Author       Notes                Mail
 * 2020-08-09     WangXi       first version        WangXi_chn@foxmail.com
 */
#include "Module_BlueToothHC06.h"

static void     Module_BlueToothHC06Init(MODULE_BLUETOOTHHC06 *module);
static void     Module_BlueToothHC06Send(MODULE_BLUETOOTHHC06 *module,FuncFlag funcflag,rt_int16_t param);
static void     Module_BlueToothHC06Feed(MODULE_BLUETOOTHHC06 *module);

static void     Module_BlueToothHC06Code(MODULE_BLUETOOTHHC06 *module,FuncFlag funcflag,rt_int16_t param);
static void     Module_BlueToothHC06Encode(MODULE_BLUETOOTHHC06 *module);

static rt_err_t Module_BlueToothHC06Handle(rt_device_t dev, rt_size_t size);

static struct rt_semaphore uartBluetoothHC06_sem;

/* Global Method */
rt_err_t Module_BlueToothHC06_Config(MODULE_BLUETOOTHHC06 *module)
{
    if( module->Method_Init     ==NULL &&
        module->Method_Handle   ==NULL &&
        module->Method_Send     ==NULL &&
        module->Method_Feed     ==NULL &&
        module->Method_Code     ==NULL &&
        module->Method_Encode   ==NULL
                
    ){  
        /* Link the Method */
        module->Method_Init         = Module_BlueToothHC06Init;
        module->Method_Handle       = Module_BlueToothHC06Handle;
        module->Method_Send         = Module_BlueToothHC06Send;
        module->Method_Feed         = Module_BlueToothHC06Feed;
        module->Method_Code         = Module_BlueToothHC06Code;
        module->Method_Encode       = Module_BlueToothHC06Encode;
        
    }
    else{
        rt_kprintf("Warning: Module BlueTooth HC06 is Configed twice\n");
        return RT_ERROR;
    }

    /* Device Init */
    module->Method_Init(module);

    return RT_EOK;
}

static void Module_BlueToothHC06Init(MODULE_BLUETOOTHHC06 *module)
{
    module->Value_uart_dev = rt_device_find(module->Property_UartDevName);
    if (!module->Value_uart_dev)
    {
        rt_kprintf("find %s failed!\n", module->Value_uart_dev);
        return;
    }
    
    rt_sem_init(&uartBluetoothHC06_sem, "uartBluetoothHC06_sem", 0, RT_IPC_FLAG_FIFO);
    
    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;  /* 初始化配置参数 */
    /* step2：修改串口配置参数 */
    config.baud_rate = BAUD_RATE_9600;        //修改波特率为 9600
    config.data_bits = DATA_BITS_8;           //数据位 8
    config.stop_bits = STOP_BITS_1;           //停止位 1
    config.bufsz     = 128;                   //修改缓冲区 buff size 为 128
    config.parity    = PARITY_NONE;           //无奇偶校验位
    
    /* step3：控制串口设备。通过控制接口传入命令控制字，与控制参数 */
    rt_device_control(module->Value_uart_dev, RT_DEVICE_CTRL_CONFIG, &config);
    
    rt_device_open(module->Value_uart_dev, RT_DEVICE_FLAG_DMA_RX);
    
    rt_device_set_rx_indicate(module->Value_uart_dev, module->Method_Handle);
    
    /* Enable Connect Status GPIO */
     rt_pin_mode(module->ConnectStatusPin, PIN_MODE_INPUT_PULLDOWN);
    
}

static void Module_BlueToothHC06Send(MODULE_BLUETOOTHHC06 *module,FuncFlag funcflag,rt_int16_t param)
{
    module->ConnectStatus = rt_pin_read(module->ConnectStatusPin);
    
    module->Method_Code(module,funcflag,param);
    
    rt_device_write(    module->Value_uart_dev, 0, 
                        &(module->Value_sendData), 
                        sizeof(module->Value_sendData));
}

static void Module_BlueToothHC06Feed(MODULE_BLUETOOTHHC06 *module)
{
    char ch;
    static char i = 0;

    while (1)
    {   
        while (rt_device_read(module->Value_uart_dev, 0, &ch, 1) == 0)
        {
            rt_sem_control(&uartBluetoothHC06_sem, RT_IPC_CMD_RESET, RT_NULL);
            rt_sem_take(&uartBluetoothHC06_sem, RT_WAITING_FOREVER);
        }
        
        if((rt_uint8_t)ch == 0xAA)
        {
            /* get the frame end flag and start encode the frame */
            module->Method_Encode(module);
            
            i = 0;
            continue;
        }
        i = (i >= 8-1) ? 8-1 : i;
        module->Value_feedData[i++] = ch;
    }   
}

static rt_err_t Module_BlueToothHC06Handle(rt_device_t dev, rt_size_t size)
{   

    rt_sem_release(&uartBluetoothHC06_sem);

    return RT_EOK;
}

static void Module_BlueToothHC06Code(MODULE_BLUETOOTHHC06 *module,FuncFlag funcflag,rt_int16_t param)
{
    module->Value_sendData[0] = 0xA5;
    module->Value_sendData[1] = 0x5A;
    
    switch (funcflag>>4)
    {
        case 0x0E: //LED Show
            module->Value_sendData[2] = 0x05;
            module->Value_sendData[3] = funcflag;
            module->Value_sendData[4] = param;
            module->Value_sendData[5] = (0x05 + funcflag + param)&0xFF;
            module->Value_sendData[6] = 0xAA;
            break;
        case 0x0C: //Param Show
            module->Value_sendData[2] = 0x06;
            module->Value_sendData[3] = funcflag;
            module->Value_sendData[4] = param >> 8;
            module->Value_sendData[5] = param & 0xFF;
            module->Value_sendData[6] = (0x06 + funcflag + (param>>8) + (param&0xFF))&0xFF;
            module->Value_sendData[7] = 0xAA;
            break;
        case 0x00: //Wave Show
            module->Value_sendData[2] = 0x06;
            module->Value_sendData[3] = funcflag;
            module->Value_sendData[4] = param >> 8;
            module->Value_sendData[5] = param & 0xFF;
            module->Value_sendData[6] = (0x06 + funcflag + (param>>8) + (param&0xFF))&0xFF;
            module->Value_sendData[7] = 0xAA;
            break;  
    }       
}

static void Module_BlueToothHC06Encode(MODULE_BLUETOOTHHC06 *module)
{
    if((rt_uint8_t)(module->Value_feedData[0])==0xA5 && (rt_uint8_t)(module->Value_feedData[1])==0x5A)
    {
        rt_uint8_t funcFlag = (rt_uint8_t)(module->Value_feedData[3])>>4;
        rt_uint8_t numFlag  = (rt_uint8_t)(module->Value_feedData[3])&0x0F;
    
        switch(funcFlag)
        {
            case 0x0B:
                module->Value_keyMask |= (0x01 << (numFlag-1));break;
        }
    }
    else
    {
        return;
    }
}

/************************ (C) COPYRIGHT 2020 WANGXI **************END OF FILE****/
